type FormatterOption = 'date' | 'datetime' | 'timestamp' | 'dateCN';
type FormatterType = string | Function | FormatterOption;

/**
 * @description 格式化日期时间为指定格式的字符串
 * @param date - 需要格式化的Date对象
 * @param formatter - 格式字符串/格式化函数/预定义选项。
 *                    支持：'date'(yyyy-MM-dd), 'datetime'(yyyy-MM-dd HH:mm:ss),
 *                   'timestamp'(yyyyMMddHHmmss), 'dateCN'(yyyy年MM月dd日)
 * @param isPad - 是否启用数字补零（默认true）
 * @returns 格式化后的日期时间字符串
 *
 * @example
 * // 使用字符串模板
 * formatDateTime(new Date(), 'YYYY/MM/DD HH:mm') // → "2023/08/15 14:05"
 *
 * @example
 * // 使用预定义格式
 * formatDateTime(new Date(), 'datetime') // → "2023-08-15 14:05:30"
 *
 * @example
 * // 使用自定义函数
 * formatDateTime(new Date(), ({ YYYY, MM }) => `${YYYY}年度${MM}月`, true)
 * // → "2023年度08月"
 */
export function formatDateTime(date: Date, formatter: FormatterType, isPad: Boolean = true): string {
  // 归一化formatter为统一函数格式
  let formatterT = normalizeFormatter(formatter);

  // 根据isPad判断是否需要补0
  function pad(value, length) {
    return isPad ? String(value).padStart(length, '0') : String(value);
  }

  // 构建日期对象(必须包含格式化所需的所有字段)
  const dateInfo = {
    YYYY: date.getFullYear(),
    MM: pad(date.getMonth() + 1, 2),
    DD: pad(date.getDate(), 2),
    HH: pad(date.getHours(), 2),
    mm: pad(date.getMinutes(), 2),
    ss: pad(date.getSeconds(), 2),
    ms: pad(date.getMilliseconds(), 3),
  };

  // 调用格式化函数生成最终结果
  return formatterT(dateInfo);
}

/**
 * @description 规范化格式化器为统一函数接口
 * @param formatter - 原始格式化参数（字符串或函数）
 * @returns 标准化后的格式化函数
 *
 * @throws 当formatter不是字符串或函数时抛出错误
 *
 */
function normalizeFormatter(formatter: FormatterType): Function {
  // 直接返回函数类型的formatter
  if (typeof formatter === 'function') {
    return formatter;
  }

  // 类型检查
  if (typeof formatter !== 'string') {
    throw new Error('formatter must be a string or function');
  }

  // 预定义格式快捷方式
  if (formatter === 'date') {
    formatter = 'YYYY-MM-DD';
  }
  if (formatter === 'datetime') {
    formatter = 'YYYY-MM-DD HH:mm:ss';
  }
  if (formatter === 'timestamp') {
    formatter = 'YYYYMMDDHHmmss';
  }
  if (formatter === 'dateCN') {
    formatter = 'YYYY年MM月DD日';
  }

  // 返回模板替换函数
  return (dateInfo) => {
    const { YYYY, MM, DD, HH, mm, ss, ms } = dateInfo;
    return formatter
      .replace('YYYY', YYYY)
      .replace('MM', MM)
      .replace('DD', DD)
      .replace('HH', HH)
      .replace('mm', mm)
      .replace('ss', ss)
      .replace('ms', ms);
  };
}
